package com.itheima.leetcode.od.b.string;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <h3>版本管理</h3>
 * 在 软件版本管理中，版本号由点分割的数字组成，例如 1.2.3 和 2.8。现在，你需要编写一个函数，计算两个版本号之间的可用版本号个数。这里的可用版本号指的是所有满足 version1 < x < version2的版本号x的个数。若 version1 >= version2 返回0.，
 * <p>
 * 输入描述
 * <p>
 * 输入两个字符串 version1和 version2，均遵循以下规定 1.版本号由数字和点组成，且至少包含一个数字, 2.点不会作为版本号的开头或结尾，也不会连续出现。 3.每个数字部分的数值忽略前导零(例如1.01和1.001视为相同) 4.两个字符串中间以英文逗号分割
 * <p>
 * 输出描述
 * <p>
 * 输出一个整数，表示可用版本号的个数。具体规则如下: 如果 version1 >= version2 ,返回0 否则，找到第一个不同的版本号段，假设在位置i，version1的该段值为v1，version2的该段值为v2。可用版本号的个数为v2-v1-1。 如果第一个不同段之后的版本段在version2中不全为0，则返回0.
 * <p>
 * 示例1：
 * <p>
 * 输入：
 * <p>
 * 1.2,1.4
 * <p>
 * 输出：
 * <p>
 * 1
 * <p>
 * 说明：
 * <p>
 * 不同段中version1为2，version2 为4，4-2-1=1
 */
public class VersionCounter {
    public static void main(String[] args) {

        String inputLine = "1.2,1.4";
        String[] versions = inputLine.split(",");
        String version1 = versions[0];
        String version2 = versions[1];

        // 计算并输出结果
        System.out.println(countAvailableVersions(version1, version2));
    }

    /**
     * 计算两个版本号之间的可用版本号个数
     * <p>
     * 规则：
     * <p>
     * 1. 如果 version1 >= version2，返回0
     * <p>
     * 2. 找到第一个不同的版本号段，假设在位置i，v1为该段值，v2为该段值
     * <p>
     * 3. 只有当version1和version2在第i段之后的所有段都为0时，
     * 才能计算可用版本号个数为 v2-v1-1
     * <p>
     * 4. 否则返回0
     */
    public static int countAvailableVersions(String version1, String version2) {
        // 解析版本号
        List<Integer> v1 = parseVersion(version1);
        List<Integer> v2 = parseVersion(version2);

        // 如果 version1 >= version2，返回0
        if (compareVersions(v1, v2) >= 0) {
            return 0;
        }

        // 补齐较短的版本号，用0填充
        int maxLen = Math.max(v1.size(), v2.size());
        List<Integer> v1Padded = new ArrayList<>(v1);
        List<Integer> v2Padded = new ArrayList<>(v2);

        while (v1Padded.size() < maxLen) {
            v1Padded.add(0);
        }
        while (v2Padded.size() < maxLen) {
            v2Padded.add(0);
        }

        // 找到第一个不同的版本号段
        int diffIndex = -1;
        for (int i = 0; i < maxLen; i++) {
            if (!v1Padded.get(i).equals(v2Padded.get(i))) {
                diffIndex = i;
                break;
            }
        }

        // 如果没有不同的段（版本号相同），返回0
        if (diffIndex == -1) {
            return 0;
        }

        // 检查两个版本号在第一个不同段之后的所有段是否都为0
        for (int i = diffIndex + 1; i < maxLen; i++) {
            if (v1Padded.get(i) != 0 || v2Padded.get(i) != 0) {
                return 0;
            }
        }

        // 计算可用版本号个数：v2[diffIndex] - v1[diffIndex] - 1
        return v2Padded.get(diffIndex) - v1Padded.get(diffIndex) - 1;
    }

    /**
     * 比较两个版本号数组
     * <p>
     * 返回: -1 如果v1 < v2, 0 如果v1 == v2, 1 如果v1 > v2
     */
    public static int compareVersions(List<Integer> v1, List<Integer> v2) {
        // 补齐较短的版本号，用0填充
        int maxLen = Math.max(v1.size(), v2.size());
        List<Integer> v1Padded = new ArrayList<>(v1);
        List<Integer> v2Padded = new ArrayList<>(v2);

        while (v1Padded.size() < maxLen) {
            v1Padded.add(0);
        }
        while (v2Padded.size() < maxLen) {
            v2Padded.add(0);
        }

        for (int i = 0; i < maxLen; i++) {
            if (v1Padded.get(i) < v2Padded.get(i)) {
                return -1;
            } else if (v1Padded.get(i) > v2Padded.get(i)) {
                return 1;
            }
        }
        return 0;
    }

    /**
     * 解析版本号字符串，返回数字列表
     * 忽略前导零，例如 "1.01.003" -> [1, 1, 3]
     */
    public static List<Integer> parseVersion(String version) {
        return Arrays.stream(version.split("\\."))
                .map(Integer::parseInt)
                .collect(Collectors.toCollection(ArrayList::new));
    }
}